<template>
  <main>
    <div class="view-top">
      <div class="header">
        <input type="text"
               placeholder="输入视图名称"
               v-model="viewName"
               class="el-input__inner">
        <el-switch v-model="isPrivate"
                   active-text="设置私密视图">
        </el-switch>
        <i class="el-icon-view"
           title="查看sql"
           @click="viewSql"></i>
        <i class="el-icon-finished"
           title="保存"
           @click="saveView"></i>
      </div>
      <div class="view-bottom">
        <aside>
          <el-tree :data="tableNameList"
                   default-expand-all>
            <span class="custom-tree-node"
                  slot-scope="{ node, data }"
                  title="双击表或视图添加到右方容器"
                  @dblclick="addDraggableElement(data)">
              <span class="iconfont"
                    v-if="data.type=='database'">&#xe603;</span>
              <span class="iconfont"
                    v-if="data.type=='table'">&#xe66d;</span>
              <span class="iconfont"
                    v-if="data.type=='view'">&#xe63d;</span>
              <span>&nbsp;{{ node.label }}</span>
              <i class="el-icon-close"
                 v-if="data.flag"
                 title="删除视图"
                 @click="() => deleteView(node,data)">
              </i>
            </span>
          </el-tree>
        </aside>
        <div class="view-container"
             id="view-container">
          <draggable v-model="tableList"
                     :move="update">
            <transition-group>
              <table-list v-for="(item,index) in tableList"
                          :key="item.name"
                          :id="item.name"
                          :data="item"
                          @change="changeCheckFields"
                          @deleteTable="deleteTable(index)">
              </table-list>
            </transition-group>
          </draggable>
          <!-- sql条件 -->
          <el-dialog :title="dialogData.title"
                     :visible.sync="dialogData.dialogFormVisible">
            <el-form :model="dialogData.form">
              <el-form-item label="添加sql条件"
                            :label-width="dialogData.formLabelWidth"
                            style="margin-left:0.3rem">
                <el-button type="primary"
                           size="small"
                           icon="el-icon-plus"
                           title="添加sql条件"
                           style="margin-left:-5.6rem"
                           @click="addCondition()">
                </el-button>
              </el-form-item>
              <el-form-item :label-width="
                           dialogData.formLabelWidth"
                            style="margin-left:-2.4rem;margin-bottom:0.2rem"
                            v-for="(condition,index) in dialogData.conditions"
                            :key="index">
                <el-select v-model="condition.source"
                           placeholder="请选择"
                           style="width:2rem;margin-left:0.5rem;margin-right:0.5rem">
                  <el-option v-for="item in options1"
                             :key="item.value"
                             :label="item.label"
                             :value="item.value">
                  </el-option>
                </el-select>
                <label for="">=</label>
                <el-select v-model="condition.target"
                           placeholder="请选择"
                           style="width:2rem;margin-left:0.5rem;margin-right:0.5rem">
                  <el-option v-for="item in options2"
                             :key="item.value"
                             :label="item.label"
                             :value="item.value">
                  </el-option>
                </el-select>
                <i class="el-icon-circle-close"
                   @click="deleteCondition(index)"></i>
                <!-- <el-input v-model="dialogData.form.name"
                          autocomplete="off"
                          style="width:2rem;margin-left:0.5rem;margin-right:0.5rem"></el-input> -->
              </el-form-item>
            </el-form>
            <div slot="footer"
                 class="dialog-footer">
              <el-button @click="dialogData.dialogFormVisible = false">取 消</el-button>
              <el-button type="primary"
                         @click="dialogData.dialogFormVisible = false">确 定</el-button>
            </div>
          </el-dialog>
          <!-- 查看sql -->
          <el-dialog title="sql"
                     :visible.sync="sqlTextVisible">
            <el-input type="textarea"
                      autosize
                      placeholder="请输入内容"
                      v-model="sql">
            </el-input>
            <div slot="footer"
                 class="dialog-footer">
              <el-button @click="sqlTextVisible = false">取 消</el-button>
              <el-button type="primary"
                         @click="sqlTextVisible = false">确 定</el-button>
            </div>
          </el-dialog>
        </div>
      </div>
    </div>
  </main>
</template>
<script>
import draggable from 'vuedraggable'
import TableList from './component/TableList'
export default {
  name: 'ViewLevel',
  components: {
    TableList,
    draggable
  },
  data () {
    return {
      isconnect: false,
      connectInfo: {},
      isView: false,
      isPrivate: false,
      tableNameList: [],
      tableList: [],
      jsPlumb: null,
      common: null,
      connections: [],
      options1: [],
      options2: [],
      dialogData: {
        id: '',
        title: 'sql条件',
        dialogFormVisible: false,
        conditions: [{ source: '', target: '' }],
        formLabelWidth: '120px'
      },
      viewName: '',
      sql: '',
      sqlTextVisible: false
    }
  },
  mounted () {
    this.$on('connectUpdate', (val, form) => {
      this.connectUpdate(val, form)
    });
    this.init()
  },
  destroyed () {
    let self = this;
    self.tableList.forEach(function (item) {
      self.jsPlumb.remove(item.name)
    })
    // self.tableNameList = []
    self.tableList = []
    self.connections = []
    self.viewName = ""
    self.jsPlumb.repaintEverything()
  },
  methods: {
    connectUpdate (val, form) {
      let self = this
      self.isconnect = val
      if (self.isconnect) {
        self.connectInfo = form
        self.$ajax({
          method: 'POST',
          url: '/view/getTable/',
          dataType: 'json',
          data: {
            'database': self.connectInfo.db,
            'userName': sessionStorage.getItem('name')
          }
        }).then(function (response) {
          console.log(response.data)
          self.tableNameList = [{
            label: sessionStorage.getItem('currentdb'),
            type: 'database',
            children: response.data.data
          }
          ]
        }).catch(function (err) {
          console.log(err)
        })
      } else {
        self.tableList.forEach(function (item) {
          self.jsPlumb.remove(item.name)
        })
        self.tableNameList = []
        self.tableList = []
        self.connections = []
        self.viewName = ""
      }
    },
    init () {
      const self = this
      self.jsPlumb = self.$jsPlumb.getInstance({
        container: 'parent',
        Connector: "Flowchart",
        // Anchors: ['Left', 'Right'],//多个锚点的位置声明
        ConnectionsDetachable: true,//连接是否可以使用鼠标默认分离
        // ConnectionOverlays: [],//附加到每个连接的默认重叠
        Container: null,//设置父级的元素，一个容器
        DoNotThrowErrors: false,//如果请求不存在的Anchor，Endpoint或Connector，是否会抛出
        DragOptions: {},//用于配置拖拽元素的参数
        DropOptions: {},//用于配置元素的drop行为的参数
        LabelStyle: { color: "black" }, //标签样式
        LogEnabled: false,//是否打开jsPlumb的内部日志记录
        // Overlays: [],//重叠
        MaxConnections: 1,//最大连接数
        PaintStyle: { lineWidth: 8, stroke: "black" },//连线样式
        ReattachConnections: false,//是否重新连接使用鼠标分离的线
        RenderMode: "svg",//默认渲染模式
        Scope: "jsPlumb_DefaultScope",//范围，标识
      })
      self.common = {
        isSource: true,
        isTarget: true,
        endpoint: 'Dot',
        paintStyle: {
          radius: 3,
          fill: 'white',
          outlineStroke: 'black',
          // strokeWidth: 1
        },
        hoverPaintStyle: {
          outlineStroke: 'gray'
        },
        connectorStyle: {
          outlineStroke: 'black',
          // strokeWidth: 1
          lineWidth: 1
        },
        connectorHoverStyle: {
          outlineStroke: 'gray'
        },
        Overlays: [['label', { labelStyle: { color: 'red' } }]],
        maxConnections: -1
      }
      self.jsPlumb.bind('connection', function (connInfo) {
        if (connInfo.connection.sourceId === connInfo.connection.targetId || connInfo.source.type !== connInfo.target.type) {
          // 删除连线
          self.jsPlumb.detach(connInfo.connection);
        } else {
          console.log(connInfo.connection)
          connInfo.connection.setLabel(connInfo.sourceId + '-' + connInfo.targetId)
          self.connections.push({
            id: connInfo.connection.id,
            title: connInfo.sourceId + '-' + connInfo.targetId,
            sourceId: connInfo.sourceId,
            targetId: connInfo.targetId,
            conditions: [{ source: '', target: '' }],
            options1: [],
            options2: []
          })
          console.log(self.connections)
        }
      })
      self.jsPlumb.bind('connectionDetached', function (info, originalEvent) {
        console.log(info);
        console.log(originalEvent);
      })
      let clickTimeout = {
        _timeout: null,
        set: function (fn) {
          let that = this;
          that.clear();
          that._timeout = window.setTimeout(fn, 300);
        },
        clear: function () {
          let that = this;
          if (that._timeout) {
            window.clearTimeout(that._timeout);
          }
        }

      }
      self.jsPlumb.bind('dblclick', function (conn) {
        clickTimeout.clear()
        self.$confirm('确定删除所点击的连接吗, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          self.connections = self.connections.filter(item => item.sourceId != conn.sourceId && item.targetId != conn.targetId)
          self.jsPlumb.deleteConnection(conn);
          self.$message({
            type: 'success',
            message: '删除成功!'
          });
        }).catch(() => {
          self.$message({
            type: 'info',
            message: '已取消删除'
          });
        });
      })
      self.jsPlumb.bind('click', function (conn) {
        clickTimeout.set(function () {
          self.dialogData.dialogFormVisible = true
          let index = self.connections.findIndex((item) => item.id === conn.id)
          self.dialogData.id = self.connections[index].id
          self.dialogData.title = self.connections[index].sourceId + '-' + self.connections[index].targetId
          self.dialogData.conditions = self.connections[index].conditions
          if (self.connections[index].options1.length == 0 && self.connections[index].options2.length == 0)
            self.$ajax({
              method: 'POST',
              url: '/view/getTableColumn/',
              dataType: 'json',
              data: {
                'tableName': self.connections[index].sourceId
              }
            }).then(function (response1) {
              self.$ajax({
                method: 'POST',
                url: '/view/getTableColumn/',
                dataType: 'json',
                data: {
                  'tableName': self.connections[index].targetId
                }
              }).then(function (response2) {
                self.connections[index].options2 = response2.data.data.map((item, index) => ({ label: item, value: index }))
                self.options2 = self.connections[index].options2
              }).catch(function (err) {
                console.log(err)
              })
              self.connections[index].options1 = response1.data.data.map((item, index) => ({ label: item, value: index }))
              self.options1 = self.connections[index].options1
            }).catch(function (err) {
              console.log(err)
            })
          else {
            self.options1 = self.connections[index].options1
            self.options2 = self.connections[index].options2
          }
        })
      })
    },
    deleteView (node, data) {
      var self = this
      self.$ajax({
        method: 'POST',
        url: '/view/deleteView/',
        dataType: 'json',
        data: {
          'viewName': data.label
        }
      }).then(function (response) {
        console.log(response.data)
        const parent = node.parent;
        const children = parent.data.children || parent.data;
        const index = children.findIndex(d => d.$treeNodeId === data.$treeNodeId);
        children.splice(index, 1);
        self.$message({ message: `视图${data.label}已删除`, type: 'success' });
      }).catch(function (err) {
        console.log(err)
      })
    },
    addDraggableElement (data) {
      const self = this
      self.$ajax({
        method: 'POST',
        url: '/view/getTableColumn/',
        dataType: 'json',
        data: {
          'tableName': data.label
        }
      }).then(function (response) {
        let fieldDescription = [...response.data.data]
        let item = {
          name: data.label,
          fieldList: response.data.data,
          description: fieldDescription,
          checkedFields: []
        }
        self.tableList.push(item)
        setTimeout(function () {
          self.jsPlumb.addEndpoint(data.label, {
            anchors: ['Left']
          }, self.common)
          self.jsPlumb.addEndpoint(data.label, {
            anchors: ['Bottom']
          }, self.common)
          self.jsPlumb.addEndpoint(data.label, {
            anchors: ['Right']
          }, self.common)
        })
      }).catch(function (err) {
        console.log(err)
      })
    },
    deleteTable (index) {
      let self = this
      let tableName = self.tableList[index].name
      self.jsPlumb.remove(tableName)
      self.tableList.splice(index, 1)
      self.connections = self.connections.filter(item => item.sourceId != tableName && item.targetId != tableName)
    },
    update () {
      const self = this
      setTimeout(function () {
        self.jsPlumb.repaintEverything()
      })
    },
    addCondition () {
      this.dialogData.conditions.push({ source: null, target: null })
    },
    deleteCondition (index) {
      this.dialogData.conditions.splice(index, 1);
    },
    changeCheckFields (tableName, fields) {
      console.log(fields);
      this.tableList.find(function (item) {
        return item.name == tableName;
      }).checkedFields = fields;
      console.log(this.tableList.find(function (item) {
        return item.name == tableName;
      }));
    },
    createSql () {
      let self = this
      let viewName = self.viewName
      let tableName = self.tableList.map(item => item.name)
      console.log('tableName', tableName)
      let fields = self.tableList.map(item => item.checkedFields)
      for (let i = 0; i < fields.length; i++) {
        fields[i] = fields[i].map(function (item) {
          if (item.value != item.description) return tableName[i] + '.' + item.value + ' as ' + item.description;
          else return tableName[i] + '.' + item.value;
        })
      }
      fields = fields.filter(function (item) { return item.length != 0 }).join(',');
      console.log(fields);
      tableName = tableName.join(',');
      console.log('connection', self.connections);
      let conditions = self.connections.map(function (item) {
        let condition1 = [];
        // console.log('option', { options1: item.options1, options2: item.options2 })
        condition1.push({ options1: item.options1, options2: item.options2 })
        for (let i = 0; i < item.conditions.length; i++) {
          let temp = Object.assign({}, item.conditions[i]);
          temp.sourceId = item.sourceId;
          temp.targetId = item.targetId;
          condition1.push(temp);
          // console.log('temp', temp);
        }
        // console.log('conditions1', condition1);
        return condition1;
      });
      console.log(conditions);
      for (let i = 0; i < conditions.length; i++) {
        for (let j = 1; j < conditions[i].length; j++) {
          console.log(conditions[i][j])
          console.log(conditions[i][0].options1)
          console.log(conditions[i][0].options2)
          console.log(conditions[i][0].options1.find(item => item.value == conditions[i][j].source));
          console.log(conditions[i][0].options2.find(item => item.value == conditions[i][j].target));
          conditions[i][j] = conditions[i][j].sourceId + '.' + conditions[i][0].options1.find(item => item.value == conditions[i][j].source).label +
            '=' + conditions[i][j].targetId + '.' + conditions[i][0].options2.find(item => item.value == conditions[i][j].target).label
        }
        conditions[i].shift();
        console.log('conditions', conditions[i]);
        conditions[i] = conditions[i].join(' and ');
      }
      conditions = conditions.join(' and ');
      self.sql = `create view ${viewName}\nas select ${fields}\nfrom ${tableName}\nwhere ${conditions}`;
      return viewName
    },
    viewSql () {
      this.createSql();
      this.sqlTextVisible = true
    },
    saveView () {
      let self = this
      let viewName = self.createSql()
      self.$ajax({
        method: 'POST',
        url: '/view/createView/',
        dataType: 'json',
        data: {
          'sql': self.sql,
          'viewName': viewName,
          'private': self.isPrivate,
          'name': sessionStorage.getItem('name'),
          'form': self.connectInfo
        }
      }).then(function (response) {
        console.log(response.data)
        let data = JSON.parse(response.data)
        if (data.flag) {
          self.$message({ message: '视图已保存', type: 'success' })
          self.$ajax({
            method: 'POST',
            url: '/view/getTable/',
            dataType: 'json',
            data: {
              'database': self.connectInfo.db,
              'userName': sessionStorage.getItem('name')
            }
          }).then(function (response) {
            console.log(response.data)
            self.tableNameList = [{
              label: self.connectInfo.db,
              children: response.data.data
            }]
          }).catch(function (err) {
            console.log(err)
          })
        }
        else self.$message.error(data.message)
      }).catch(function (err) {
        console.log(err)
      })
    },

  }
}
</script>
<style lang="stylus" scoped>
main
  display flex
  height 100%
  padding 0
  .view-top
    flex 1
    height 100%
    background red
    .header
      width 100%
      height 0.25rem
      background #e6e6e6
      border-bottom 0.01rem solid #fff
      font-size 0.15rem
      .el-input__inner
        width 2rem
        height 0.24rem
        margin-left 0.4rem
        margin-right 0.2rem
      .el-switch
        margin-right 6.4rem
      i
        display inline-block
        margin-right 0.2rem
        cursor pointer
      i:hover
        color #3689ff
    .view-bottom
      display flex
      width 100%
      height 7.1rem
      background #fff
      aside
        display inline-block
        width 2.5rem
        height 100%
        background #fff
        border 0.01rem solid #ecf5ff
        user-select none
        .el-tree
          background #fff !important
          .el-icon-close
            position absolute
            line-height 0.18rem
            right 0.05rem
            color red
          .el-icon-close:hover
            background #e6e6e6
            border-radius 50%
      .view-container
        background #fff
        flex 1
.el-icon-circle-close:hover
  color red
  cursor pointer
</style>